package api;



import java.util.HashSet;
import java.util.Iterator;

import indi.zjh.dp.access.Api;
import indi.zjh.dp.access.ApiContext;
import indi.zjh.dp.db.Configuration;
import indi.zjh.dp.db.Session;
import indi.zjh.dp.orm.Query;
import indi.zjh.dp.orm.Result;
import indi.zjh.dp.type.GSet;
import indi.zjh.dp.verify.CharNotEmptyRule;
import indi.zjh.dp.verify.Check;
import indi.zjh.dp.verify.StringSetRule;
import indi.zjh.dp.verify.ValueRangeRule;
import log.Label;
import log.Log;

public class SearchLogsApi extends Api {

	private static int MAX_LABEL_COUNT = 32; // 最大的标签数
	
	@Override
	public void process(ApiContext ctx) throws Exception {
		// TODO Auto-generated method stub
		Session session = null;
		try
		{
			// 获取标签
			String[] labels = new String[MAX_LABEL_COUNT];
			int len = 0;
			for(int i = 0; i < MAX_LABEL_COUNT; ++i)
			{
				String label = ctx.getRequestParamValue("label"+i).trim();
				if(label == null || label.isEmpty() || label.length() == 0)
				{
					break;
				}
				labels[len++] = label;
			}
			// 获取模式
			String modestr = ctx.getRequestParamValue("mode").toLowerCase().trim();
			if(modestr != null && !modestr.isEmpty() && modestr.length() > 0)
			{
				Check.data(modestr).desc("日志标签组合模式错误").rule(new StringSetRule(GSet.createStringSet().addString("and").addString("or")));
			}
			else
			{
				modestr = "and";
			}
			
			// 获取级别
			String levelstr = ctx.getRequestParamValue("level").trim().toLowerCase();
			if(levelstr != null && !levelstr.isEmpty() && levelstr.length() > 0)
			{
				Check.data(levelstr).desc("日志级别错误").rule(new StringSetRule(GSet.createStringSet().addString("debug").addString("info").addString("business").addString("warn").addString("error").addString("fatal")));
			}
			//获取输出格式
			String output = ctx.getRequestParamValue("output").toLowerCase().trim();
			if(output != null && !output.isEmpty() && output.length() > 0)
			{
				Check.data(output).desc("日志输出格式错误").rule(new StringSetRule(GSet.createStringSet().addString("console").addString("html").addString("json")));
			}
			else
			{
				output = "html";
			}
			// 获取内容
			String pagesize = ctx.getRequestParamValue("ps").trim();
			String page = ctx.getRequestParamValue("p").trim();
			if(pagesize != null && !pagesize.isEmpty() && pagesize.length() > 0)
			{
				Check.data(pagesize).desc("日志分页大小必须为数字").rule(new ValueRangeRule(1, 100));
			}
			else
			{
				pagesize = "50";
			}
			
			if(page != null && !page.isEmpty() && page.length() > 0)
			{
				Check.data(page).desc("日志分页必须为数字").rule(new ValueRangeRule(0, 5000));
			}
			else
			{
				page = "0";
			}
			
			int pagesizev = Integer.parseInt(pagesize);
			int pagev = Integer.parseInt(page);
			
			
			int level = -1;
			if(levelstr.equals("debug"))
				level = Log.LEVEL_DEBUG;
			else if(levelstr.equals("info"))
				level = Log.LEVEL_INFO;
			else if(levelstr.equals("business"))
				level = Log.LEVEL_BUSINESS;
			else if(levelstr.equals("warn"))
				level = Log.LEVEL_WARN;
			else if(levelstr.equals("error"))
				level = Log.LEVEL_ERROR;
			else if(levelstr.equals("fatal"))
				level = Log.LEVEL_FATAL;
			System.out.println("level="+level);
			
			session = Configuration.getSessionFactory().createSession();
			
			Query<Log> query = new Query<Log>(session);
			HashSet<Long> finalids = new HashSet<Long>();
			
			Result<Log> result = null;
			
			// 没有使用标签
			if(len == 0)
			{
				if(level == -1)
					query.find(Log.class);
				else
					query.find(Log.class, "`level` = "+level);
				result = query.order(Log.class, "`_id` DESC").limit(pagesizev * pagev, pagesizev).result();
			}
			// 有使用标签
			else 
			{
				if(modestr.equals("or"))
				{
					for(int i = 0; i < len; ++i)
					{
						if(level == -1)
							query.find(Log.class);
						else
							query.find(Log.class, "`level` = "+level);
						Result<Long> ids = query.association(Log.class, Label.class, "`name` = '"+labels[i]+"'").idResult();
						Iterator<Long> iter = ids.iterator();
						while(iter.hasNext())
						{
							finalids.add(iter.next());
						}
					}
				}
				else
				{
					for(int i = 0; i < len; ++i)
					{
						if(level == -1)
							query.find(Log.class);
						else
							query.find(Log.class, "`level` = "+level);
						Result<Long> ids = query.association(Log.class, Label.class, "`name` = '"+labels[i]+"'").idResult();
						if(i == 0)
						{
							Iterator<Long> iter = ids.iterator();
							while(iter.hasNext())
							{
								finalids.add(iter.next());
							}
						}
						else
						{
							HashSet<Long> tmpset = new HashSet<Long>();
							Iterator<Long> iter = ids.iterator();
							while(iter.hasNext())
							{
								tmpset.add(iter.next());
							}
							finalids.retainAll(tmpset);
						}
					}
				}
				
				if(finalids.size() > 0)
				{
					String[] idString = new String[finalids.size()];
					Iterator<Long> niter = finalids.iterator();
					int index = 0;
					while(niter.hasNext())
					{
						idString[index++] = niter.next().toString();
					}
					result = query.find(Log.class, "`_id` IN ("+String.join(",", idString)+")").order(Log.class, "`_id` DESC").limit(pagesizev * pagev, pagesizev).result();
				}
				else
				{
					result = query.find(Log.class, "`_id` = 0").order(Log.class, "`_id` DESC").limit(pagesizev * pagev, pagesizev).result();
					ctx.writeResponse("没有找到匹配的日志<br>");
				}
			}
			
			// 显示
			Iterator<Log> liter = result.iterator();
			if(output.equals("html"))
			{
				while(liter.hasNext())
				{
					Log curLog = liter.next();
					ctx.writeResponse(curLog.getLevelString() + " : " + curLog.getCreated() + " : " + curLog.getContent()+"<br>");
				}
				ctx.writeResponse("OK");
			}
			else if(output.equals("console"))
			{
				while(liter.hasNext())
				{
					Log curLog = liter.next();
					ctx.writeResponse(curLog.getLevelString() + " : " + curLog.getCreated() + " : " + curLog.getContent()+"\n");
				}
				ctx.writeResponse("OK");
			}
			else if(output.equals("json"))
			{
				String[] tmpstr = new String[result.count()];
				int i = 0;
				ctx.writeResponse("{\"code\":0,\"desc\":\"OK\",\"datalen\":"+result.count()+",\"data:\":");
				while(liter.hasNext())
				{
					Log curLog = liter.next();
					//ctx.writeResponse("[{\"Level\":"+curLog.getLevelString() + " : " + curLog.getCreated() + " : " + curLog.getContent()+"\n");
					tmpstr[i++] = "[{\"level\":\""+curLog.getLevelString()+"\",\"time\":\""+curLog.getCreated()+"\",\"content\":\""+curLog.getContent()+"\"}]";
				}
				ctx.writeResponse(String.join(",", tmpstr));
				ctx.writeResponse("}");
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
			if(session != null)
			{
				session.rollback();
			}
			ctx.writeResponse("FAIL");
		}
		finally 
		{
			if(session != null)
			{
				session.close();
			}
		}
	}

}
